package gy.chen;

import com.google.gson.Gson;
import com.squareup.okhttp.*;

import javax.swing.*;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TinyPngProcess {

    private List<File> fileList = new LinkedList<>();
    private JTextArea infoArea;

    public void compress(String rootPath, JTextArea infoArea){
        this.infoArea = infoArea;
        fileList.clear();
        filterAllPictures(new File(rootPath));
        System.out.println(fileList.size() + "个文件要处理");
        compress();
    }

    private void filterAllPictures(File file){
        String name = file.getName();
        if(file.isDirectory()){
            //只处理不是build目录的内容.原始图
            if(!name.equalsIgnoreCase("build")){
                for(File f:file.listFiles()){
                    filterAllPictures(f);
                }
            }
        }else{
            if(name.endsWith(".jpg") || name.endsWith(".png") || name.endsWith(".jpeg")){
                fileList.add(file);
            }
        }
    }

    final static String url = "https://tinypng.com/web/shrink";

    private int currentIndex = 0;
    private boolean cancelTiny = false;
    private int totalLength = 0;

    public void cancel() {
        this.cancelTiny = true;
    }

    private void compress(){
        infoArea.append("共"+fileList.size()+"个文件需要处理\r\n");
        if(fileList.size()>0){
            int total = fileList.size();
            infoArea.setRows(fileList.size());
            currentIndex = 0;
            //获取可用线程数量
            int availableProcessors = Runtime.getRuntime().availableProcessors();

            ExecutorService fixedThreadPool = Executors.newFixedThreadPool(availableProcessors / 2 + 1);
//            ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);
            for (int i = 0; i < fileList.size(); i++) {
                File file = fileList.get(i);

                fixedThreadPool.execute(() -> {

                    try {
                        if (!cancelTiny) {
                            UploadBean uploadBean = uploadImage(file);

                            SwingUtilities.invokeLater(() -> {
                                currentIndex ++;
                                String msg = currentIndex + "/"+ total +"["+(uploadBean==null?"FAIL":" OK ")+"]"+file.getAbsolutePath() +
                                        " " + (uploadBean == null ? file.length() : uploadBean.getInput().getSize())
                                        + " -> " + (uploadBean == null ? file.length() : uploadBean.getOutput().getSize()) + "\r\n";
                                totalLength +=msg.length();
                                infoArea.append(msg);
                                infoArea.setCaretPosition(totalLength);
//                                System.out.println(msg);
                                try {
                                    Thread.sleep(1L);
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                }
                            });
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                });
            }
        }
    }

    /**
     * 上传
     *
     * @param sourceFile
     * @return
     * @throws IOException
     */
    public UploadBean uploadImage(File sourceFile) throws IOException {
        if (sourceFile == null || !sourceFile.exists()) return null;

        String type = sourceFile.getName().endsWith(".png")?"image/png":"image/jpeg";

        Request request = new Request.Builder()
                .addHeader("content-length", String.valueOf(sourceFile.length()))
                .addHeader("Content-Type", type)
                .addHeader("referer", "https://tinypng.com/")
                .addHeader("X-Forwarded-For", getRandomIP())
                .url(url)
                .post(RequestBody.create(MediaType.parse(type), sourceFile))
                .build();

//        System.out.println(sourceFile.getAbsolutePath()+":"+type);
        OkHttpClient okHttpClient = new OkHttpClient();
        okHttpClient.setReadTimeout(120, TimeUnit.SECONDS);
        okHttpClient.setConnectTimeout(120, TimeUnit.SECONDS);
        Response response = okHttpClient.newCall(request).execute();

        if (!response.isSuccessful()){
//            System.out.println("出现错误!"+sourceFile.getAbsolutePath());
            return null;
        }

        UploadBean uploadBean = new Gson().fromJson(response.body().string(), UploadBean.class);

        if (uploadBean == null || uploadBean.getOutput() == null || uploadBean.getOutput().getUrl().isEmpty())
            return null;

        InputStream inputStream = okHttpClient.newCall(new Request.Builder()
                .get()
                .url(uploadBean.getOutput().getUrl())
                .build()
        ).execute().body().byteStream();


        saveToFile(sourceFile.getAbsolutePath(), inputStream);
        return uploadBean;
    }


    /**
     * 保存图片
     *
     * @param fileName
     * @param in
     * @throws IOException
     */
    private void saveToFile(String fileName, InputStream in) throws IOException {

        int BUFFER_SIZE = 1024;
        byte[] buf = new byte[BUFFER_SIZE];
        int size = 0;

        BufferedInputStream bis = new BufferedInputStream(in);
        FileOutputStream fos = new FileOutputStream(fileName);

        //保存文件
        while ((size = bis.read(buf)) != -1) {
            fos.write(buf, 0, size);
        }

        fos.close();
        bis.close();
    }

    Random random = new Random();
    private String getRandomIP(){
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<4;i++) {
            sb.append(random.nextInt(255)).append(".");
        }
        sb.deleteCharAt(sb.length()-1);
//        System.out.println(sb.toString());
        return sb.toString();
    }
}
